package com.icedevcloud.upms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.icedevcloud.common.core.exception.ApiException;
import com.icedevcloud.common.security.util.SecurityUtil;
import com.icedevcloud.upms.controller.admin.permission.dto.AddPermissionReqDto;
import com.icedevcloud.upms.controller.admin.permission.dto.PermissionQueryReqDto;
import com.icedevcloud.upms.controller.admin.permission.dto.RouterResDto;
import com.icedevcloud.upms.controller.admin.permission.dto.UpdatePermissionReqDto;
import com.icedevcloud.upms.entity.SysPermission;
import com.icedevcloud.upms.mapper.SysPermissionMapper;
import com.icedevcloud.upms.service.ISysPermissionService;
import com.icedevcloud.upms.service.ISysRolePermissionService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 权限表 服务实现类
 * </p>
 *
 * @author XiaoBingBy
 * @since 2023-08-13
 */
@RequiredArgsConstructor
@Service
public class SysPermissionServiceImpl extends ServiceImpl<SysPermissionMapper, SysPermission> implements ISysPermissionService {

    private final ISysRolePermissionService iSysRolePermissionService;

    @Override
    public List<RouterResDto> getRouters() {
        List<SysPermission> sysPermissions;
        if (SecurityUtil.isSuperAdminRole()) {
            sysPermissions = this.list(
                    Wrappers.<SysPermission>lambdaQuery()
                            .eq(SysPermission::getStatus, 1)
                            .in(SysPermission::getPermType, 'D', 'M')
                            .orderByAsc(SysPermission::getSort)
            );
        } else {
            Long userId = SecurityUtil.getCurrentLoginUserId();
            sysPermissions = baseMapper.selectUserPermissionByUserId(userId);
        }

        List<RouterResDto> routerResDtos = sysPermissions.stream().map(item -> {
            RouterResDto routerResDto = new RouterResDto();
            routerResDto.setId(item.getId());
            routerResDto.setPid(item.getPid());
            routerResDto.setPath(item.getPath());
            routerResDto.setName(item.getPathName());
            routerResDto.setComponent(item.getComponent());
            // routerResDto.setRedirect(item.getRedirect());

            RouterResDto.RouteMeta routeMeta = new RouterResDto.RouteMeta();
            routeMeta.setTitle(item.getPermName());
            routeMeta.setIcon(item.getIcon());
            if (item.getHidden() != null) {
                Boolean hidden = item.getHidden() == 1 ? Boolean.TRUE : Boolean.FALSE;
                routeMeta.setHideMenu(hidden);
                routeMeta.setHideBreadcrumb(hidden);
            }
            routeMeta.setFrameSrc(item.getUrl());
            routeMeta.setIgnoreKeepAlive(true);
            routerResDto.setMeta(routeMeta);
            return routerResDto;
        }).collect(Collectors.toList());

        routerResDtos = getChildPerms(routerResDtos, 0);
        routerResDtos.forEach(item -> {
            if (CollUtil.isNotEmpty(item.getChildren())) {
                item.setRedirect(item.getPath() + "/" + item.getChildren().get(0).getPath());
            }
        });
        return routerResDtos;
    }

    @Override
    public List<String> getUserPermCodeByUserId(Long userId) {
        List<String> permCodes = baseMapper.selectUserPermCodeByUserId(userId);
        return permCodes;
    }

    @Override
    public List<SysPermission> permissionList(PermissionQueryReqDto reqDto) {
        List<SysPermission> sysPermissions = this.list(
                Wrappers.<SysPermission>lambdaQuery()
                        .eq(StrUtil.isNotBlank(reqDto.getPermName()), SysPermission::getPermName, reqDto.getPermName())
                        .eq(reqDto.getStatus() != null, SysPermission::getStatus, reqDto.getStatus())
                        .orderByAsc(SysPermission::getSort)
        );
        return sysPermissions;
    }

    @Override
    public Boolean add(AddPermissionReqDto reqDto) {
        SysPermission saveData = BeanUtil.copyProperties(reqDto, SysPermission.class);
        return this.save(saveData);
    }

    @Override
    public Boolean update(UpdatePermissionReqDto reqDto) {
        SysPermission sysPermission = this.getById(reqDto.getId());
        if (sysPermission == null) {
            throw new ApiException("权限信息不存在");
        }
        SysPermission updateData = BeanUtil.copyProperties(reqDto, SysPermission.class);
        return this.updateById(updateData);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean delete(Long id) {
        SysPermission sysPermission = this.getById(id);
        if (sysPermission == null) {
            throw new ApiException("权限信息不存在");
        }
        // 判断是否有子节点
        List<SysPermission> sysPermissions = this.list(
                Wrappers.<SysPermission>lambdaQuery()
                        .eq(SysPermission::getPid, id)
        );
        if (CollUtil.isNotEmpty(sysPermissions)) {
            throw new ApiException("存在子节点删除失败");
        }
        iSysRolePermissionService.removeRolePermissionByPermissionId(id);
        this.removeById(id);
        return Boolean.TRUE;
    }

    /**
     * 根据父节点的ID获取所有子节点
     *
     * @param list     分类表
     * @param parentId 传入的父节点ID
     * @return String
     */
    private List<RouterResDto> getChildPerms(List<RouterResDto> list, long parentId) {
        List<RouterResDto> returnList = new ArrayList<>();
        for (RouterResDto t : list) {
            // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
            if (t.getPid() == parentId) {
                recursionFn(list, t);
                returnList.add(t);
            }
        }
        return returnList;
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<RouterResDto> list, RouterResDto t) {
        // 得到子节点列表
        List<RouterResDto> childList = list.stream().filter(n -> n.getPid().equals(t.getId())).collect(Collectors.toList());
        t.setChildren(childList);
        for (RouterResDto tChild : childList) {
            // 判断是否有子节点
            if (list.stream().anyMatch(n -> n.getPid().equals(tChild.getId()))) {
                recursionFn(list, tChild);
            }
        }
    }


}
